package com.sskj.depth.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;

import com.sskj.depth.R;
import com.sskj.depth.bean.IDepthData;


import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class DepthMapView extends View {
    private long PRESS_TIME = 300;
    private int mWidth;
    //圆点半径
    private int mDotRadius = 2;
    //圆圈半径
    private int mCircleRadius = 8;
    //    private float mGridWidth;
    //底部价格区域高度
    private int mBottomPriceHeight;
    //右侧委托量绘制个数
    private int mLineCount;
    //背景颜色
    private int mBackgroundColor;

    private boolean mIsHave;
    //是否是长按
    private boolean mIsLongPress;

    //最大的委托量
    private double mMaxVolume;
    private double mMultiple;
    private int mLastPosition;
    private int mDrawWidth = 0;
    private int mDrawHeight;
    //触摸点的X轴值
    private int mEventX;
    //文案绘制画笔
    private Paint mTextPaint;
    //买入区域边线绘制画笔
    private Paint mBuyLinePaint;
    //卖出区域边线绘制画笔
    private Paint mSellLinePaint;
    //买入区域绘制画笔
    private Paint mBuyPathPaint;
    //卖出取悦绘制画笔
    private Paint mSellPathPaint;
    //选中时圆点绘制画笔
    private Paint mRadioPaint;
    //选中时中间文案背景画笔
    private Paint mSelectorBackgroundPaint;

    private Path mBuyPath = new Path();
    private Path mSellPath = new Path();
    private boolean isDrawText = true;

    private List<IDepthData> mBuyData = new ArrayList<>();
    private List<IDepthData> mSellData = new ArrayList<>();

    //    价格显示精度限制
    public int mPriceLimit = 4;
    public int mVolumeLimit = 0;

    private SparseArray<IDepthData> mMapX;
    private SparseArray<Float> mMapY;
    private Double[] mBottomPrice;
    private GestureDetector mGestureDetector;

    private int selectPadding = 5;
    private int selectTextColor = Color.WHITE;
    private int selectBackgroundColor = Color.BLACK;
    private int textColor;
    private long mLastDownTime;
    private long nowTime;
    private float mGridWidthBuy;
    private float mGridWidthSell;

    public DepthMapView(Context context) {
        this(context, null);
    }

    public DepthMapView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public DepthMapView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs);
    }

    public void setSelectTextColor(int selectTextColor) {
        this.selectTextColor = selectTextColor;
    }

    public void setSelectBackgroundColor(int selectBackgroundColor) {
        this.selectBackgroundColor = selectBackgroundColor;
    }

    private void init(AttributeSet attrs) {
        mBottomPriceHeight = 40;
        mMapX = new SparseArray<>();
        mMapY = new SparseArray<>();
        mBottomPrice = new Double[4];
        mBuyData = new ArrayList<>();
        mSellData = new ArrayList<>();
        mGestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() {
            @Override
            public void onLongPress(MotionEvent e) {
                mIsLongPress = true;
                invalidate();
            }
        });

        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTextPaint.setTextAlign(Paint.Align.RIGHT);

        mBuyLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBuyLinePaint.setStyle(Paint.Style.STROKE);
        mBuyLinePaint.setTextAlign(Paint.Align.CENTER);
        mBuyPathPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

        mSellLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mSellLinePaint.setStyle(Paint.Style.STROKE);
        mSellLinePaint.setTextAlign(Paint.Align.CENTER);
        mSellPathPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

        mRadioPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mRadioPaint.setTextAlign(Paint.Align.CENTER);
        mSelectorBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

        TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.DepthMapView);
        if (typedArray != null) {
            try {
                mLineCount = typedArray.getInt(R.styleable.DepthMapView_depth_mv_line_count, 4);
                mDotRadius = typedArray.getDimensionPixelSize(R.styleable.DepthMapView_depth_mv_dot_radius, ResourceUtil.dp2px(getContext(), mDotRadius));
                mCircleRadius = typedArray.getDimensionPixelSize(R.styleable.DepthMapView_depth_mv_circle_radius, ResourceUtil.dp2px(getContext(), mCircleRadius));
                mBackgroundColor = typedArray.getColor(R.styleable.DepthMapView_depth_mv_background_color, ResourceUtil.getColor(getContext(), R.color.depth_background));
                mBuyLinePaint.setStrokeWidth(typedArray.getDimensionPixelSize(R.styleable.DepthMapView_depth_mv_line_width, ResourceUtil.dp2px(getContext(), 1.5f)));
                mSellLinePaint.setStrokeWidth(typedArray.getDimensionPixelSize(R.styleable.DepthMapView_depth_mv_line_width, ResourceUtil.dp2px(getContext(), 1.5f)));
                mTextPaint.setColor(typedArray.getColor(R.styleable.DepthMapView_depth_mv_text_color, ResourceUtil.getColor(getContext(), R.color.depth_text_color)));
                textColor = (typedArray.getColor(R.styleable.DepthMapView_depth_mv_text_color, ResourceUtil.getColor(getContext(), R.color.depth_text_color)));
                mTextPaint.setTextSize(typedArray.getDimension(R.styleable.DepthMapView_depth_mv_text_size, ResourceUtil.getDimension(getContext(), R.dimen.depth_text_size)));
                mBuyLinePaint.setColor(typedArray.getColor(R.styleable.DepthMapView_depth_mv_buy_line_color, ResourceUtil.getColor(getContext(), R.color.depth_buy_line)));
                mSellLinePaint.setColor(typedArray.getColor(R.styleable.DepthMapView_depth_mv_sell_line_color, ResourceUtil.getColor(getContext(), R.color.depth_sell_line)));
                mBuyPathPaint.setColor(typedArray.getColor(R.styleable.DepthMapView_depth_mv_buy_path_color, ResourceUtil.getColor(getContext(), R.color.depth_buy_path)));
                mSellPathPaint.setColor(typedArray.getColor(R.styleable.DepthMapView_depth_mv_sell_path_color, ResourceUtil.getColor(getContext(), R.color.depth_sell_path)));
                mSelectorBackgroundPaint.setColor(typedArray.getColor(R.styleable.DepthMapView_depth_mv_selector_background_color, ResourceUtil.getColor(getContext(), R.color.depth_selector)));
            } finally {
                typedArray.recycle();
            }
        }
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        this.mWidth = w;
        mDrawWidth = mWidth / 2;
        mDrawHeight = h - mBottomPriceHeight;
    }

    public void setData(List<IDepthData> buyData, List<IDepthData> sellData) {
        mMaxVolume = 0;
        mBuyData.clear();
        mBuyData.addAll(buyData);
        if (buyData.size() > 0) {
//            //买入数据按价格进行排序
//            Collections.sort(mBuyData, new ComparePrice());
//            for (int i = 0; i < buyData.size(); i++) {
//                if (mMaxVolume < buyData.get(i).getVolume()) {
//                    mMaxVolume = buyData.get(i).getVolume();
//                }
//            }
            mMaxVolume = buyData.get(0).getVolume();
            //修改底部买入价格展示
            mBottomPrice[0] = mBuyData.get(0).getPrice();
            mBottomPrice[1] = mBuyData.get(mBuyData.size() - 1).getPrice();
        } else {
            mMaxVolume = 0;
            mBottomPrice[0] = 0d;
            mBottomPrice[1] = 0d;
        }

        mSellData.clear();
        mSellData.addAll(sellData);
        if (sellData.size() > 0) {
            //卖出数据按价格进行排序
//            Collections.sort(mSellData, new ComparePrice());
//            for (int i = 0; i < sellData.size(); i++) {
//                if (mMaxVolume < sellData.get(i).getVolume()) {
//                    mMaxVolume = sellData.get(i).getVolume();
//                }
//            }
            mMaxVolume = Math.max(mMaxVolume, sellData.get(sellData.size() - 1).getVolume());
            //修改底部卖出价格展示
            mBottomPrice[2] = mSellData.get(0).getPrice();
            mBottomPrice[3] = mSellData.get(mSellData.size() > 1 ? mSellData.size() - 1 : 0).getPrice();
        } else {
            mMaxVolume = Math.max(0, mMaxVolume);
            mBottomPrice[2] = 0d;
            mBottomPrice[3] = 0d;
        }
        mMaxVolume = mMaxVolume * 1.05f;
        mMultiple = mMaxVolume / mLineCount;
        invalidate();
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        getParent().requestDisallowInterceptTouchEvent(mIsLongPress);
        return super.dispatchTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mEventX = (int) event.getX();
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                mIsLongPress = false;
                mLastDownTime = System.currentTimeMillis();
                break;
            case MotionEvent.ACTION_MOVE:
                nowTime = System.currentTimeMillis();
                if (nowTime - mLastDownTime > PRESS_TIME) {
                    mIsLongPress = true;
                }
                mLastDownTime = System.currentTimeMillis();
                if (event.getPointerCount() == 1) {
                    if (onPointShowListener != null) {
                        onPointShowListener.onPointChange(true);
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                nowTime = System.currentTimeMillis();
                if (nowTime - mLastDownTime > PRESS_TIME) {
                    mIsLongPress = true;
                }
                break;
            case MotionEvent.ACTION_CANCEL:
                nowTime = System.currentTimeMillis();
                if (nowTime - mLastDownTime > PRESS_TIME) {
                    mIsLongPress = true;
                }
                if (onPointShowListener != null) {
                    onPointShowListener.onPointChange(false);
                }
                invalidate();
                break;
            default:
                break;
        }
        invalidate();
        mGestureDetector.onTouchEvent(event);
        return true;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(mBackgroundColor);
        canvas.save();
        //绘制买入区域
        drawBuy(canvas);
        //绘制卖出区域
        drawSell(canvas);
        //绘制界面相关文案

        drawText(canvas);
        canvas.restore();
    }

    private void drawBuy(Canvas canvas) {
        mGridWidthBuy = (mDrawWidth * 1.0f / Math.max(1, mBuyData.size()));
        mBuyPath.reset();
        mMapX.clear();
        mMapY.clear();
        float x;
        float y;
        for (int i = 0; i < mBuyData.size(); i++) {
            if (i == 0) {
                canvas.drawLine(0, getY(mBuyData.get(0).getVolume()), mGridWidthBuy, getY(mBuyData.get(0).getVolume()), mBuyLinePaint);
                mBuyPath.moveTo(0, mDrawHeight);
                mBuyPath.lineTo(0, getY(mBuyData.get(0).getVolume()));
                mBuyPath.lineTo(mGridWidthBuy, getY(mBuyData.get(0).getVolume()));
            }
            y = getY(mBuyData.get(i).getVolume());
            if (i >= 1) {
                canvas.drawLine(mGridWidthBuy * i, getY(mBuyData.get(i - 1).getVolume()), mGridWidthBuy * i, y, mBuyLinePaint);
                canvas.drawLine(mGridWidthBuy * i, y, mGridWidthBuy * (i + 1), y, mBuyLinePaint);
                mBuyPath.lineTo(mGridWidthBuy * i, y);
                mBuyPath.lineTo(mGridWidthBuy * (i + 1), y);
            }


            x = mGridWidthBuy * i;
            mMapX.put((int) x, mBuyData.get(i));
            mMapY.put((int) x, y);
            if (i == mBuyData.size() - 1) {
                mBuyPath.lineTo(mGridWidthBuy * (i + 1), mDrawHeight);
                mBuyPath.close();
            }
        }
        canvas.drawPath(mBuyPath, mBuyPathPaint);
    }

    private void drawSell(Canvas canvas) {
        mGridWidthSell = (mDrawWidth * 1.0f / Math.max(1, mSellData.size()));
        mSellPath.reset();
        float x;
        float y;
        for (int i = 0; i < mSellData.size(); i++) {
            if (i == 0) {
                mSellPath.moveTo(mDrawWidth, mDrawHeight);
                mSellPath.lineTo(mDrawWidth, getY(mSellData.get(0).getVolume()));
                mSellPath.lineTo(mDrawWidth + mGridWidthSell, getY(mSellData.get(0).getVolume()));
                canvas.drawLine(mDrawWidth, getY(mSellData.get(0).getVolume()), mDrawWidth + mGridWidthSell, getY(mSellData.get(0).getVolume()), mSellLinePaint);
            }
            y = getY(mSellData.get(i).getVolume());
            if (i >= 1) {
                mSellPath.lineTo(mDrawWidth + mGridWidthSell * i, y);
                mSellPath.lineTo(mDrawWidth + mGridWidthSell * (i + 1), y);
                canvas.drawLine(mGridWidthSell * i + mDrawWidth, getY(mSellData.get(i - 1).getVolume()),
                        mGridWidthSell * i + mDrawWidth, y, mSellLinePaint);
                canvas.drawLine(mGridWidthSell * i + +mDrawWidth, y,
                        mGridWidthSell * (i + 1) + mDrawWidth, y, mSellLinePaint);
            }
            if (i == mSellData.size() - 1) {
                mSellPath.lineTo(mDrawWidth + mGridWidthSell * (i + 1), mDrawHeight);
                mSellPath.close();
            }
            x = (mGridWidthSell * i) + mDrawWidth;
            mMapX.put((int) x, mSellData.get(i));
            mMapY.put((int) x, y);
        }
        canvas.drawPath(mSellPath, mSellPathPaint);
    }

    private void drawText(Canvas canvas) {

        mTextPaint.setColor(textColor);
        mTextPaint.setTextAlign(Paint.Align.RIGHT);
        mTextPaint.setStyle(Paint.Style.FILL);
        double value;
        String str;
        if (isDrawText) {
            for (int j = 0; j < mLineCount; j++) {
                value = mMaxVolume - mMultiple * j;
                str = getVolumeValue(value);
                canvas.drawText(str, mWidth, mDrawHeight / mLineCount * j + 30, mTextPaint);
            }
            int size = mBottomPrice.length;
            int height = mDrawHeight + mBottomPriceHeight / 2 + 10;
            if (size > 0 && mBottomPrice[0] != null) {
                String data = getValue(mBottomPrice[0]);
                canvas.drawText(data, mTextPaint.measureText(data), height, mTextPaint);
                data = getValue(mBottomPrice[1]);
                canvas.drawText(data, mDrawWidth - 10, height, mTextPaint);
                data = getValue(mBottomPrice[2]);
                canvas.drawText(data, mDrawWidth + mTextPaint.measureText(data) + 10, height, mTextPaint);
                data = getValue(mBottomPrice[3]);
                canvas.drawText(data, mWidth, height, mTextPaint);
            }
        }
        if (mIsLongPress) {

            drawSelectorView(canvas);

        }
    }

    private void drawSelectorView(Canvas canvas) {
        mIsHave = true;
        mTextPaint.setTextAlign(Paint.Align.LEFT);
        Float y = 0f;
        String volume;
        int dataX;
        if (mEventX < mDrawWidth) {
            int start = (int) (mEventX / mGridWidthBuy);
            dataX = (int) ((start) * mGridWidthBuy);
            y = mMapY.get(dataX);
            volume = getVolumeValue(mMapX.get(dataX).getVolume());
        } else {
            int start = (int) ((mEventX - mDrawWidth) / mGridWidthSell);
            dataX = (int) (mDrawWidth + (start) * mGridWidthSell);
            y = mMapY.get(dataX);
            volume = getVolumeValue(mMapX.get(dataX).getVolume());
        }
        if (y == null) {
            return;
        }
        if (mEventX < mDrawWidth) {
            canvas.drawCircle(mEventX, y, mCircleRadius, mBuyLinePaint);
            mRadioPaint.setColor(ResourceUtil.getColor(getContext(), R.color.depth_buy_line));
        } else {
            canvas.drawCircle(mEventX, y, mCircleRadius, mSellLinePaint);
            mRadioPaint.setColor(ResourceUtil.getColor(getContext(), R.color.depth_sell_line));
        }
        canvas.drawCircle(mEventX, y, mDotRadius, mRadioPaint);


        Paint.FontMetrics metrics = mTextPaint.getFontMetrics();
        float textHeight = metrics.descent - metrics.ascent;
        float width = mTextPaint.measureText(volume);
        if (mEventX < mWidth / 2) {
            mTextPaint.setColor(selectBackgroundColor);
            canvas.drawRect(new RectF(0, y - textHeight / 2, width + selectPadding, y + textHeight / 2), mTextPaint);
            mTextPaint.setColor(selectTextColor);
            canvas.drawText(getVolumeValue(mMapX.get(dataX).getVolume()), 0 + selectPadding, y + 10, mTextPaint);
        } else {
            mTextPaint.setColor(selectBackgroundColor);
            canvas.drawRect(new RectF(mWidth - width - selectPadding, y - textHeight / 2, mWidth + selectPadding, y + textHeight / 2), mTextPaint);
            mTextPaint.setColor(selectTextColor);
            canvas.drawText(getVolumeValue(mMapX.get(dataX).getVolume()), mWidth - width, y + 10, mTextPaint);
        }
        String price = getValue(mMapX.get(dataX).getPrice());
        float priceWith = mTextPaint.measureText(price);
        mTextPaint.setColor(selectBackgroundColor);
        canvas.drawRect(new RectF(mEventX - priceWith / 2 - selectPadding, mDrawHeight, mEventX + priceWith / 2 + selectPadding, mDrawHeight + mBottomPriceHeight), mTextPaint);
        mTextPaint.setColor(selectTextColor);
        canvas.drawText(price, mEventX - priceWith / 2, mDrawHeight + mBottomPriceHeight / 2 + 10, mTextPaint);

    }

    public class ComparePrice implements Comparator<IDepthData> {
        @Override
        public int compare(IDepthData o1, IDepthData o2) {
            double str1 = o1.getPrice();
            double str2 = o2.getPrice();
            return Double.compare(str1, str2);
        }
    }

    /**
     * 成交量获取Y轴坐标
     *
     * @param volume
     * @return
     */
    private float getY(double volume) {
        return Double.valueOf(mDrawHeight - (mDrawHeight) * volume / mMaxVolume).floatValue();
    }

    private String getValue(double value) {

        return String.format("%." + mPriceLimit + "f", value);
    }

    public void setDrawText(boolean drawText) {
        isDrawText = drawText;
    }

    private String getVolumeValue(double value) {
        return String.format("%." + mVolumeLimit + "f", value);
    }


    public interface OnPointShowListener {
        void onPointChange(boolean show);
    }

    public OnPointShowListener getOnPointShowListener() {
        return onPointShowListener;
    }

    public void setOnPointShowListener(OnPointShowListener onPointShowListener) {
        this.onPointShowListener = onPointShowListener;
    }

    private OnPointShowListener onPointShowListener;

}